package com.xianguo.datacenter.controller;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import static java.nio.file.StandardOpenOption.READ;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.format.support.FormattingConversionServiceFactoryBean;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSONObject;
import com.google.gson.JsonObject;
import com.xianguo.datacenter.domain.CenterFolder;
import com.xianguo.datacenter.domain.Disk;
import com.xianguo.datacenter.domain.jsonMessage;
import com.xianguo.datacenter.download.Thread.Download.DownloadState;
import com.xianguo.datacenter.download.Thread.DownloadUtil;
import com.xianguo.datacenter.service.CommonService;
import com.xianguo.datacenter.thread.FileReadThread;
import com.xianguo.datacenter.util.cpu;

@Controller
public class CommonController {
	
	@Autowired
	private CommonService commonService;

	//获取磁盘列表
	@RequestMapping("/common/disks")
	@ResponseBody
	public String addCommtype(HttpServletRequest request,HttpSession session){
		List<Disk> disks = commonService.getDiskList();
		String disksJSON = JSONObject.toJSONString(disks);
		return disksJSON;
	}
	
	//获取路径下文件和文件夹
	@RequestMapping(value="/common/folder",method = RequestMethod.POST,produces = "application/json; charset=utf-8")
	@ResponseBody
	public String getCenterFolder(String path,HttpServletRequest request,HttpSession session){
		CenterFolder cfo = commonService.getFolder(path);
		String cfoJSON = JSONObject.toJSONString(cfo);
		return cfoJSON;
	}
	
	//新建Http下载
	@RequestMapping(value="/common/addDownloadHttpFile",method = RequestMethod.POST,produces = "application/json; charset=utf-8")
	@ResponseBody
	public String addDownloadHttp(String path,String fileName,String url,HttpServletRequest request,HttpSession session){
		jsonMessage message = new jsonMessage();
		message.setMessage("success");
		String messageJSON = JSONObject.toJSONString(message);
		commonService.AddHttpdownload(url, path, fileName);
		return messageJSON;
	}
	
	//新建百度云下载
	@RequestMapping(value="/common/addDownloadBaiDuYunFile",method = RequestMethod.POST,produces = "application/json; charset=utf-8")
	@ResponseBody
	public String addDownloadBaiDuYun(String path,String url,HttpServletRequest request,HttpSession session){
		Map<String, String> map = commonService.addBaiDuYunDownload(url, path, request.getSession().getServletContext().getRealPath(""));
		String BaiDuYunJSON = JSONObject.toJSONString(map);
		return BaiDuYunJSON;
	}
	
	//输入百度云验证码
	@RequestMapping(value="/common/setBaiDuYunVCod",method = RequestMethod.GET,produces = "application/json; charset=utf-8")
	@ResponseBody
	public String setBaiDuYunVCod(String uid,String vcod){
		Map<String, String> map = commonService.setBaiDuYunVCode(uid, vcod);
		String messageJSON = JSONObject.toJSONString(map);
		return messageJSON;
	}
	
	//获取下载列表
	@RequestMapping(value="/common/getDownloadList",method=RequestMethod.GET,produces = "application/json; charset=utf-8")
	@ResponseBody
	public String getDownloadList(HttpServletRequest request,HttpSession session){
		List<com.xianguo.datacenter.download.Thread.Download> downloadList = DownloadUtil.downloadList;
		List<com.xianguo.datacenter.download.Thread.Download> downloadTempList = DownloadUtil.downloadTempList;
		Map<String, List<com.xianguo.datacenter.download.Thread.Download>> map = new HashMap<String, List<com.xianguo.datacenter.download.Thread.Download>>();
		map.put("downloadList", downloadList);
		map.put("downloadTempList", downloadTempList);
		String downloadsJSON = JSONObject.toJSONString(map);
		return downloadsJSON;
	}
	
	//下载服务器文件
	@RequestMapping("/common/downloadFile")  
	public void Download(String path,HttpServletRequest request,HttpServletResponse response)throws Exception{
		//构造文件
		File file = new File(path);
        //获取输入流  
        InputStream bis = new BufferedInputStream(new FileInputStream(file));  
        //假如以中文名下载的话  
        String filename = file.getName();
        //转码，免得文件名中文乱码  
        filename = URLEncoder.encode(filename,"UTF-8");  
        //设置文件下载头  
        response.addHeader("Content-Disposition", "attachment;filename=" + filename);    
        //1.设置文件ContentType类型，这样设置，会自动判断下载文件类型    
        response.setContentType("multipart/form-data");   
        BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());  
        byte[] data = new byte[4096];
        int len = 0;  
        while((len = bis.read(data)) != -1){
        	out.write(data, 0, len);
            out.flush();
        }
        out.close();  
	}
	
	//图片流
	@RequestMapping("/common/imgIo")  
	public void imgIo(String path,HttpServletRequest request,HttpServletResponse response)throws Exception{
		//构造文件
		File file = new File(URLDecoder.decode(path, "utf-8"));
        //获取输入流  
        InputStream bis = new BufferedInputStream(new FileInputStream(file));  
        BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());  
        byte[] data = new byte[4096];
        int len = 0;  
        while((len = bis.read(data)) != -1){
        	out.write(data, 0, len);
            out.flush();
        }
        out.close();  
	}
	
	//视频流
	@RequestMapping("/common/mediaIo")  
	public void mediaIo(String path,HttpServletRequest request,HttpServletResponse response)throws Exception{
		path = URLDecoder.decode(path,"utf-8");
		Pattern RANGE_PATTERN = Pattern.compile("bytes=(?<start>\\d*)-(?<end>\\d*)");
		int BUFFER_LENGTH = 1024 * 16;
		long EXPIRE_TIME = 1000 * 60 * 60 * 24;
		Path video = Paths.get(path);
		int length = (int) Files.size(video);
		int start = 0;
		int end = length - 1;

		String range = request.getHeader("Range");
		range=range==null?"":range;
		Matcher matcher = RANGE_PATTERN.matcher(range);
		if (matcher.matches()) {
			String startGroup = matcher.group("start");
			start = startGroup.isEmpty() ? start : Integer.valueOf(startGroup);
			start = start < 0 ? 0 : start;
			String endGroup = matcher.group("end");
			end = endGroup.isEmpty() ? end : Integer.valueOf(endGroup);
			end = end > length - 1 ? length - 1 : end;
		}
		int contentLength = end - start + 1;
		response.reset();
		response.setBufferSize(BUFFER_LENGTH);
		response.setHeader("Content-Disposition", String.format("inline;filename=\"%s\"", path.substring(path.indexOf("\\"))));
		response.setHeader("Accept-Ranges", "bytes");
		response.setDateHeader("Last-Modified", Files.getLastModifiedTime(video).toMillis());
		response.setDateHeader("Expires", System.currentTimeMillis() + EXPIRE_TIME);
		response.setContentType(Files.probeContentType(video));
		response.setHeader("Content-Range", String.format("bytes %s-%s/%s", start, end, length));
		response.setHeader("Content-Length", String.format("%s", contentLength));
		response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
		
		int bytesRead;
		int bytesLeft = contentLength;
		ByteBuffer buffer = ByteBuffer.allocate(BUFFER_LENGTH);
		try (SeekableByteChannel input = Files.newByteChannel(video, READ);
		OutputStream output = response.getOutputStream()) {
			input.position(start);
			while ((bytesRead = input.read(buffer)) != -1 && bytesLeft > 0) {
				buffer.clear();
				output.write(buffer.array(), 0, bytesLeft < bytesRead ? bytesLeft : bytesRead);
				bytesLeft -= bytesRead;
			}
		}
	}
	
	//获取设备运行信息
	@RequestMapping(value="/common/moninfo",method = RequestMethod.GET,produces = "application/json; charset=utf-8")
	@ResponseBody
	public String getMonInfo(HttpServletRequest request,HttpSession session){
		try {
			cpu c = new cpu();
			String monJSON = JSONObject.toJSONString(c.getMonitorInfo());
			return monJSON;
		} catch (Exception e) {
			return "";
		}
	}
	
	//暂停或继续下载
	@RequestMapping(value="/common/changeDownloadSate",method = RequestMethod.POST,produces = "application/json; charset=utf-8")
	@ResponseBody
	public String changeDownloadSate(String UID,DownloadState isDownloading){
		Map<String, String> map = new HashMap<String, String>();
		try {
			commonService.changeDownloadState(UID, isDownloading);
			map.put("message", "success");
		} catch (Exception e) {
			map.put("message", "error");
		}
		String messageJSON = JSONObject.toJSONString(map);
		return messageJSON;
	}
	@RequestMapping(value="/common/selectType",method = RequestMethod.GET,produces = "application/json; charset=utf-8")
	@ResponseBody
	public String selectType() {
		return JSONObject.toJSONString(commonService.selectType());
	}
	
	/**
	 * 定时任务 每天晚上1点读取磁盘文件
	 * 作者:鲜果
	 * 日期:2018年7月3日
	 * void
	 */
	@Scheduled(cron= "0 0 1 * * ?")
	//@Scheduled(cron="0 */3 * * * ?")
	public void readFile() {
		System.out.println("任务开始");
		commonService.deleteAllFile();
		List<Disk> disks = commonService.getDiskList();
    	for(Disk item : disks) {
    		String disPath = item.getSymbol();
    		CenterFolder folders = commonService.getFolder(disPath);
    		for(CenterFolder itemFolder : folders.getFolders()) {
    			FileReadThread runnable = new FileReadThread(itemFolder.getPath(),commonService);
    			Thread thread = new Thread(runnable);
    			thread.start();
    		}
    	}
	}
}
